# -*- coding: utf-8 -*-
'''
Модуль реализует ряд функция модуля math для dimension.Dim
'''
import math
import dimension

FEATURES = ('sin',
            'cos',
            'tan',
            'asin',
            'acos',
            'atan',
            'deg',
            'rad',
            'sqrt',
            '**')
#Здесь опишем некоторые константы которые мы сможем использовать в формуле
pi = math.pi

def rad(angle):
    '''
    Преобразует градусы в радианы
    '''
    return angle*math.pi/180

def deg(angle):
    return angle*180/math.pi

def sin(dim):
    '''
    Реализует функцию sin() для dimension.Dim
    '''
    try:
        x = math.sin(rad(dim.value))
        x_max = math.sin(rad(dim.value+dim.up_tolerance))
        x_min = math.sin(rad(dim.value+dim.un_tolerance))
        return dimension.Dim(x, x_max-x, x_min-x)
    except:
        return math.sin(dim)

def cos(dim):
    '''
    Реализует функцию cos() для dimension.Dim
    '''
    try:
        x = math.cos(rad(dim.value))
        x_max = math.cos(rad(dim.value+dim.up_tolerance))
        x_min = math.cos(rad(dim.value+dim.un_tolerance))
        return dimension.Dim(x, x_max-x, x_min-x)
    except:
        return math.cos(dim)

def tan(dim):
    '''
    Реализует функцию tan() для dimension.Dim
    '''
    try:
        x = math.tan(rad(dim.value))
        x_max = math.tan(rad(dim.value+dim.up_tolerance))
        x_min = math.tan(rad(dim.value+dim.un_tolerance))
        return dimension.Dim(x, x_max-x, x_min-x)
    except:
        return math.tan(dim)

def asin(dim):
    '''
    Реализует функцию atan() для dimension.Dim
    '''
    try:
        x = deg(math.asin(dim.value))
        x_max = deg(math.asin(dim.value+dim.up_tolerance))
        x_min = deg(math.asin(dim.value+dim.un_tolerance))
        return dimension.Dim(x, x_max-x, x_min-x)
    except:
        return deg(math.asin(dim))

def acos(dim):
    '''
    Реализует функцию atan() для dimension.Dim
    '''
    try:
        x = deg(math.acos(dim.value))
        x_max = deg(math.acos(dim.value+dim.up_tolerance))
        x_min = deg(math.acos(dim.value+dim.un_tolerance))
        return dimension.Dim(x, x_max-x, x_min-x)
    except:
        return deg(math.acos(dim))

def atan(dim):
    '''
    Реализует функцию atan() для dimension.Dim
    '''
    try:
        x = deg(math.atan(dim.value))
        x_max = deg(math.atan(dim.value+dim.up_tolerance))
        x_min = deg(math.atan(dim.value+dim.un_tolerance))
        return dimension.Dim(x, x_max-x, x_min-x)
    except:
        return deg(math.atan(dim))

def sqrt(dim):
    '''
    Реализует функцию atan() для dimension.Dim
    '''
    try:
        x = math.sqrt(dim.value)
        x_max = math.sqrt(dim.value+dim.up_tolerance)
        x_min = math.sqrt(dim.value+dim.un_tolerance)
        return dimension.Dim(x, x_max-x, x_min-x)
    except:
        return math.acos(dim)

def dim_in_formula(formula, dim_name):
    '''
    Возвращает True если размер dim_name присутствует в формуле
    '''
    op = ('+', '-', '/', '*', ' ', '(', ')')
    result = False
    f = formula
    pos = 0
    max_pos = 0
    while True:#ищим размер в формуле
        pos = f.find(dim_name, pos)
        if pos > max_pos:
            max_pos = pos
        if pos != -1:
            rep = False
            if f == dim_name: #Первый случай формула состоит из одной переменной
                rep = True
                pos = max_pos + 1
            elif pos == 0:
                if f[pos+len(dim_name)] in op: #Переменная в начале строки
                    rep = True
            elif pos+len(dim_name) == len(f): #Переменная в конце строки
                if f[pos-1] in op:
                    rep = True
            elif f[pos-1] in op:
                if f[pos+len(dim_name)] in op:
                    rep = True
            if rep:
                result = True
            pos += 1
        else:
        #    break
            rep = False
        if pos < max_pos:
            break
    return result
